package com.tanhua.server.service.impl;


import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.RecommendUserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.service.MovementService;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementServiceImpl implements MovementService {

    @DubboReference
    private MovementApi movementApi;

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private MqMessageService mqMessageService;

    /**
     * 发布动态
     *
     * @param movement
     * @param imageContent
     */
    @Override
    public void publishMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        //判断发布动态的内容是否存在
        if (StringUtils.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }
        //获取当前登录的用户ID
        Long id = UserHolder.getUserId();
        //将文件上传到oss中，并获取请求地址
        List<String> pathList = new ArrayList<>();
        for (MultipartFile file : imageContent) {
            String path = ossTemplate.upload(file.getOriginalFilename(), file.getInputStream());
            pathList.add(path);
        }
        //将数据封装到movement中
        movement.setMedias(pathList);
        movement.setUserId(id);
        //调用API保存动态
        String movementId = movementApi.publish(movement);
        //发送消息到RabbitMq，完成动态内容审核
        mqMessageService.sendAudiMessage(movementId);
    }

    /**
     * 查询个人动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    @Override
    public PageResult findMyMovement(Long userId, Integer page, Integer pagesize) {
        List<Long> idList = new ArrayList<>();
        idList.add(userId);
        //根据用户ID查询动态内容，返回一个PageResult对象
        PageResult pr = movementApi.findMove(idList, page, pagesize);
        //获取PageResult对象中的item列表对象
        List<Movement> items = (List<Movement>) pr.getItems();
        //判断是否为空
        if (items == null) {
            return pr;
        }
        //不为空，循环列表对象
        UserInfo info = userInfoApi.findById(userId);
        List<MovementsVo> voList = new ArrayList<>();
        for (Movement item : items) {
            //一个movement对象构建一个vo对象
            MovementsVo vo = MovementsVo.init(info, item);
            voList.add(vo);
        }
        pr.setItems(voList);
        //构建返回值
        return pr;
    }


    /**
     * 查询好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    @Override
    public PageResult friendMove(Integer page, Integer pagesize) {
        Long id = UserHolder.getUserId();
        //获取所有好友的ID
        List<Long> userIds = recommendUserApi.findFriendIDs(id);
        //调用api获取pr对象
        PageResult pr = movementApi.findMove(userIds, page, pagesize);
        List<Movement> moveItems = (List<Movement>) pr.getItems();
        return getPageResult(userIds, page, pagesize, moveItems);
    }

    private PageResult getPageResult(List<Long> userIds, Integer page, Integer pagesize, List<Movement> moveItems) {
        if (moveItems == null) {
            return new PageResult();
        }
        //调用api获取好友的个人信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, new UserInfo());
        List<MovementsVo> voList = new ArrayList<>();
        //遍历每一个动态对象，每个动态对象只能属于某一个用户
        for (Movement moveItem : moveItems) {
            if (moveItem != null) {
                if (map.get(moveItem.getUserId()) != null) {
                    //封装userInfo和movement对象到vo对象中
                    MovementsVo vo = MovementsVo.init(map.get(moveItem.getUserId()), moveItem);
                    //修复点赞状态bug，判断存入Redis中的hashKey是否存在
                    String key = Constants.MOVEMENTS_INTERACT_KEY + moveItem.getId().toHexString();
                    String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                    Boolean flag = redisTemplate.opsForHash().hasKey(key, hashKey);
                    if (flag) {
                        vo.setHasLiked(1);
                    }
                    String lovehashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
                    Boolean flag1 = redisTemplate.opsForHash().hasKey(key, lovehashKey);
                    if (flag1) {
                        vo.setHasLoved(1);
                    }
                    voList.add(vo);
                }
            }
        }
        return new PageResult(page, pagesize, 0L, voList);
    }

    /**
     * 查询推荐动态（这个较难）
     *
     * @param page
     * @param pagesize
     * @return
     */
    @Override
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        //1.从Redis中获取推荐数据
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //2.判断推荐数据是否存在
        List<Movement> movementList = Collections.EMPTY_LIST;
        List<Long> ids = Collections.EMPTY_LIST;
        if (StringUtils.isEmpty(redisValue)) {
            //3.不存在，调用API随机构造10条数据
            movementList = movementApi.randomMovements(pagesize);
            //获取这些动态的用户ID
            ids = CollUtil.getFieldValues(movementList, "userId", Long.class);
        } else {
            //4.存在，对pid进行处理
            String[] values = redisValue.split(",");
            //判断当前页的起始条数是否小于数组总数
            if ((page - 1) * pagesize < values.length) {
                List<Long> pids = Arrays.stream(values).skip((page - 1) * pagesize).limit(pagesize)
                        .map(e -> Long.valueOf(e))
                        .collect(Collectors.toList());
                //5.调用API根据pid数组查询动态数据
                movementList = movementApi.findMovementsByPids(pids);
                ids = CollUtil.getFieldValues(movementList, "userId", Long.class);
            }
        }
        return getPageResult(ids, page, pagesize, movementList);

    }

    /**
     * 动态详情
     *
     * @param id
     * @return
     */
    @Override
    public MovementsVo movementDetail(String id) {
        Movement movement = movementApi.movementDetails(id);
        if (movement != null) {
            UserInfo info = userInfoApi.findById(movement.getUserId());
            return MovementsVo.init(info, movement);
        } else {
            return null;
        }
    }

    /**
     * 查看访客列表
     */
    @Override
    public List<VisitorsVo> visitors() {
        //查询上次查看时间
        String key = Constants.VISITORS_USER;
        String hashKey = UserHolder.getUserId().toString();
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date = StringUtils.isEmpty(value) ? null : Long.valueOf(value);
        //调用api查询列表数据 List<Visitors>
        List<Visitors> visitors = visitorsApi.queryVisitorsList(UserHolder.getUserId(), date);
        if (CollUtil.isEmpty(visitors)) {
            return new ArrayList<>();
        }
        //提取用户ID
        List<Long> visitorUserIds = CollUtil.getFieldValues(visitors, "visitorUserId", Long.class);
        //查看用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(visitorUserIds, null);
        List<VisitorsVo> voList = new ArrayList<>();
        for (Visitors visitor : visitors) {
            UserInfo userInfo = map.get(visitor.getVisitorUserId());
            if (userInfo != null) {
                VisitorsVo vo = VisitorsVo.init(userInfo, visitor);
                voList.add(vo);
            }
        }
        return voList;
    }
}
